package com.junxonline.plat.service.position.impl;

import com.junxonline.plat.dao.model.Menu;
import com.junxonline.plat.dao.model.Position;
import com.junxonline.common.dao.pojo.JsTree;
import com.junxonline.common.dao.pojo.JsTreeState;
import com.junxonline.plat.dao.repository.MenuRepository;
import com.junxonline.plat.dao.repository.PositionRepository;
import com.junxonline.plat.dao.vo.*;
import com.junxonline.common.exception.CommonBizException;
import com.junxonline.common.util.CommonUtils;
import com.junxonline.plat.service.position.PositionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class PositionServiceImpl implements PositionService {

    @Autowired
    private PositionRepository positionRepository;

    @Autowired
    private MenuRepository menuRepository;

    /**
     * 获取部门岗位树数据
     *
     * @return
     */
    @Override
    public List<JsTree> getPositionTree() {
        List<JsTree> jsTrees = new ArrayList<>();

        // 获取所有的部门岗位数据
        List<Position> positions = positionRepository.findAll(new Sort(Sort.Direction.ASC, "positionSort"));

        // 构建部门岗位树
        for (Position position : positions) {
            JsTree jsTree = new JsTree();
            jsTree.setId(position.getPositionId().toString());
            jsTree.setText(position.getPositionName());

            // 为公司部门设置父级Id为# （JsTree数据规范）
            if (CommonUtils.isEmpty(position.getPositionParentId())) {
                jsTree.setParent("#");
            } else {
                jsTree.setParent(position.getPositionParentId());
            }


            // 为公司设置图标
            if (position.getPositionType().equals(0)) {
                jsTree.setIcon("fa fa-copyright icon-state-default");
            }
            // 为部门设置图标
            else if (position.getPositionType().equals(1)) {
                jsTree.setIcon("fa fa-sitemap icon-state-default");
            }
            // 为岗位设置图标
            else {
                jsTree.setIcon("fa fa-user-circle-o icon-state-default");
            }

            // 为公司部门设置默认展开
            if (CommonUtils.isEmpty(position.getPositionParentId())) {
                jsTree.setState(new JsTreeState(true, false, false));
            }
            // 为岗位设置默认不展开
            else {
                jsTree.setState(new JsTreeState(false, false, false));
            }


            jsTrees.add(jsTree);
        }

        return jsTrees;
    }

    /**
     * 获取父级公司部门树数据
     *
     * @param vo
     * @return
     */
    @Override
    public List<JsTree> getParentPositionTree(PositionTypesVO vo) {

        Integer[] positionTypes = vo.getPositionTypes();

        List<JsTree> jsTrees = new ArrayList<>();

        // 获取所有的部门岗位数据
        List<Position> positions = positionRepository.findPositionsByPositionTypeIn(positionTypes, new Sort(Sort.Direction.ASC, "positionSort"));

        // 构建部门岗位树
        for (Position position : positions) {
            JsTree jsTree = new JsTree();
            jsTree.setId(position.getPositionId().toString());
            jsTree.setText(position.getPositionName());

            // 为公司部门设置父级Id为# （JsTree数据规范）
            if (CommonUtils.isEmpty(position.getPositionParentId())) {
                jsTree.setParent("#");
            }
            else if (vo.getPositionTypes().length == 1) {
                jsTree.setParent("#");
            }
            else {
                jsTree.setParent(position.getPositionParentId());
            }

            // 为公司设置图标
            if (position.getPositionType().equals(0)) {
                jsTree.setIcon("fa fa-copyright icon-state-default");
            }
            // 为部门设置图标
            else if (position.getPositionType().equals(1)) {
                jsTree.setIcon("fa fa-sitemap icon-state-default");
            }

            jsTree.setState(new JsTreeState(true, false, false));
            jsTrees.add(jsTree);
        }

        return jsTrees;
    }

    /**
     * 获取部门岗位数据
     *
     * @param vo
     * @return
     */
    @Override
    public Position getPosition(QueryPositionVO vo) {

        Position position = positionRepository.findByPositionId(vo.getPositionId());

        return position;
    }

    /**
     * 筛选查询部门岗位
     *
     * @param pageVO
     * @param vo
     * @return
     */
    @Override
    public PageVO queryPosition(PageVO pageVO, QueryPositionVO vo) {
        PageRequest pageRequest = PageRequest.of(pageVO.getPage() - 1, pageVO.getLimit(), new Sort(Sort.Direction.ASC, "positionId"));

        Page<Position> page = positionRepository.findAll(new Specification<Position>() {
            @Override
            public Predicate toPredicate(Root<Position> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> params = new ArrayList<>();
                String positionName = vo.getPositionName();
                Integer positionType = vo.getPositionType();
                Integer positionStatus = vo.getPositionStatus();

                if (CommonUtils.isNotEmpty(positionName)) {
                    params.add(criteriaBuilder.like(root.get("positionName"), "%" + positionName + "%"));
                }

                if (CommonUtils.isNotEmpty(positionType)) {
                    params.add(criteriaBuilder.equal(root.get("positionType"), positionType));
                }

                if (CommonUtils.isNotEmpty(positionStatus)) {
                    params.add(criteriaBuilder.equal(root.get("positionStatus"), positionStatus));
                }

                return criteriaBuilder.and(params.toArray(new Predicate[params.size()]));
            }
        }, pageRequest);

        List<Position> positions = page.getContent();

        for (Position position : positions) {

            // 替换部门岗位类型
            switch (position.getPositionType()) {
                case 0:
                    position.setPositionTypeString("公司");
                    break;
                case 1:
                    position.setPositionTypeString("部门");
                    break;
                case 2:
                    position.setPositionTypeString("岗位");
                    break;
                default:
                    break;
            }

            // 替换部门岗位状态
            switch (position.getPositionStatus()) {
                case 0:
                    position.setPositionStatusString("<span class=\"layui-badge layui-bg-green\">启用</span>");
                    break;
                case 1:
                    position.setPositionStatusString("<span class=\"layui-badge\">禁用</span>");
                    break;
                default:
                    break;
            }

        }

        pageVO.setTotal(page.getTotalElements());
        pageVO.setData(positions);

        return pageVO;
    }

    /**
     * 添加部门岗位
     *
     * @param vo
     * @return
     */
    @Override
    public boolean addPosition(PositionVO vo) {
        Position position = new Position();
        position.setPositionName(vo.getPositionName());
        position.setPositionType(vo.getPositionType());

        String parentId = vo.getPositionParentId();
        position.setPositionParentId(parentId);

        if (CommonUtils.isNotEmpty(parentId)) {
            // 获取部门岗位父级名称
            Position tempPosition = positionRepository.findByPositionId(Long.parseLong(parentId));

            if (CommonUtils.isEmpty(tempPosition)) {
                throw CommonBizException.SYSTEM_ERROR;
            }

            position.setPositionParentName(tempPosition.getPositionName());
        }

        position.setPositionLevel(vo.getPositionLevel());
        position.setPositionSort(vo.getPositionSort());
        position.setPositionStatus(vo.getPositionStatus());

        positionRepository.save(position);

        return true;
    }

    /**
     * 修改部门岗位
     *
     * @param vo
     * @return
     */
    @Override
    public boolean editPosition(PositionVO vo) {

        Position position = positionRepository.findByPositionId(vo.getPositionId());

        if (CommonUtils.isEmpty(position)) {
            throw CommonBizException.SYSTEM_ERROR;
        }

        position.setPositionName(vo.getPositionName());
        position.setPositionType(vo.getPositionType());

        String parentId = vo.getPositionParentId();
        position.setPositionParentId(parentId);

        if (CommonUtils.isNotEmpty(parentId)) {
            // 获取部门岗位父级名称
            Position tempPosition = positionRepository.findByPositionId(Long.parseLong(parentId));

            if (CommonUtils.isEmpty(tempPosition)) {
                throw CommonBizException.SYSTEM_ERROR;
            }

            position.setPositionParentName(tempPosition.getPositionName());
        }

        position.setPositionLevel(vo.getPositionLevel());
        position.setPositionSort(vo.getPositionSort());
        position.setPositionStatus(vo.getPositionStatus());

        positionRepository.save(position);

        return true;
    }

    /**
     * 删除部门岗位
     *
     * @param positionIds
     * @return
     */
    @Override
    public boolean delPosition(Long[] positionIds) {

        List<Position> positions = positionRepository.findByPositionIdIn(positionIds);

        for (Position position : positions) {

            List<Menu> menus = position.getMenus();

            // 删除与该部门岗位相关联的中间表的所有菜单数据
            for (Menu menu : menus) {
                Long menuId = menu.getMenuId();
                Long positionId = position.getPositionId();
                positionRepository.deletePositionMenuIn(menuId, positionId);
            }

            List<Map<String, BigInteger>> userIds = positionRepository.findUserPositionsByPositionId(position.getPositionId());

            // 删除与该部门岗位相关联的中间表的所有用户数据
            for (Map<String, BigInteger> userRole : userIds) {
                Long userId = userRole.get("user_id").longValue();
                Long positionId = userRole.get("position_id").longValue();
                positionRepository.deleteUserPositionIn(userId, positionId);
            }

            // 再删除部门岗位
            positionRepository.delete(position);
        }

        return true;
    }

    /**
     * 设置权限
     *
     * @param positionIds
     * @param menuIds
     * @return
     */
    @Override
    public boolean setPermission(Long[] positionIds, Long[] menuIds) {
        // 先校验菜单id集合
        List<Menu> menus = menuRepository.findByMenuIdIn(menuIds);

        // 校验部门岗位id集合
        List<Position> positions = positionRepository.findByPositionIdIn(positionIds);

        // 删除与所有部门岗位关联的所有菜单数据
        for (Position position : positions) {

            if (!position.getPositionType().equals(2)) {
                throw CommonBizException.POSITION_SET_PERMISSION_ERROR;
            }

            List<Menu> deleteMenus = position.getMenus();

            for (Menu menu : deleteMenus) {
                positionRepository.deletePositionMenuIn(menu.getMenuId(), position.getPositionId());
            }

        }

        // 再添加新的菜单数据
        for (Position position : positions) {

            for (Menu menu : menus) {
                positionRepository.savePositionMenuIn(menu.getMenuId(), position.getPositionId());
            }

        }

        return true;
    }

}
